#pragma once
#include "CVHeader.h"
#include "GlobalHeader.h"

class ImageHandler
{
public:
	ImageHandler(void);
	~ImageHandler(void);
	void			setImageWithPointer(IplImage* pImage);
	void			setMaskImgWithPointer(IplImage* pImage);

	void			createImage(CvSize size, int depth, int channels);
	void			releaseImage(IplImage** pImage);
	void			releaseAll();

	bool			loadImage(const char* fileName);
	bool			loadDepth(const char* fileName);

	static void		setPixelValue(IplImage* pImage, int h, int w, void* val);
	static float	getPixelValue(IplImage* pImage, int h, int w );
	static void		setGridValue(IplImage* pImage, int jGpos, int iGpos, void* val);
	
	//get image pointers
	IplImage*		getImage();
	IplImage*		getSobelDx();
	IplImage*		getSobelDy();
	IplImage*		getSobelMg();
	IplImage*		getSobelAg();
	IplImage*       getMaskImg();

	int				getGridWidth();
	int				getGridHeight();
	CvMat*			getByteMat();
	
	//construct the gradient image with mag and angle
	void			constructGradientImage();

	//init grid width and height
	void			initGridInfo();

	void			generateDepTemplateByteMat();

	void			generateDepTargetByteMat();

	void			generateImgTemplateByteMat();

	void			generateImgTargetByteMat();

	std::vector<Saliency>& getCntKeyPoints();
	std::vector<Saliency>& getDepKeyPoints();

	void			generateCntKeyPoints();
	void			generateDepKeyPoints();

	template<typename T>
	float			getStdVal( const std::vector<T>& valVec);

private:
	uchar			buildImgTemplateBytePattern(GRID_POS hPos, GRID_POS wPos);

	uchar			buildImgTargetBytePattern(GRID_POS hPos, GRID_POS wPos);

	uchar			buildDepTemplateBytePattern(GRID_POS hPos, GRID_POS wPos);

	uchar			buildDepTargetBytePattern(GRID_POS hPos, GRID_POS wPos);

	Point2D			getPixPosByGridPos(GRID_POS hPos, GRID_POS wPos);
	//discretize angle into 0~6
	int				discretizeOrientation(float angle, float div  = ANGLER_DIV_7);
	static  bool	MagCompareFunc( const MagWithPos& mag1, const MagWithPos& mag2 );
	static  bool    SaliencyCompareFunc(const Saliency& sal1, const Saliency& sal2);
	bool			isGridInObjectArea(GRID_POS jGPos, GRID_POS iGPos);

	float*			generate2DBuffer(IplImage* pImage);
	void			bufferToImage(float* buffer, IplImage* pImage, int width, int height);

	
private:
	//FIX: using ImpImage is obsolete
	IplImage*       m_maskImg;
	IplImage*		m_pImage;
	IplImage*		lp_sobel_dx;
	IplImage*		lp_sobel_dy;
	IplImage*		lp_sobel_mg;
	IplImage*		lp_sobel_ag;
	int				m_gridWidth;
	int				m_gridHeight;
	//stores the BYTE pattern corresponds to each grid
	CvMat*			m_pByteMat;
	std::vector<Saliency> m_CntKeyPointsVec;
	std::vector<Saliency> m_depKeyPointsVec;
};

template<typename T>
float	ImageHandler::getStdVal(const std::vector<T>& valVec)
{
	float avgVal = 0.0, stdVal = 0.0;
	for (size_t i = 0; i < valVec.size(); ++i)
	{
		avgVal += valVec[i];
	}
	avgVal /=valVec.size();
	for (size_t i=0; i<valVec.size(); ++i)
	{
		stdVal += fabs(valVec[i] - avgVal);
	}
	stdVal /= valVec.size();
	return stdVal;
}